package com.atguigu.gmall.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.IpUtil;
import com.atguigu.gmall.user.model.UserInfo;
import com.atguigu.gmall.user.mapper.UserInfoMapper;
import com.atguigu.gmall.user.service.UserInfoService;
import com.atguigu.gmall.user.util.AreaInfo;
import com.atguigu.gmall.user.util.BaiDuService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 用户表 业务实现类
 *
 * @author atguigu
 * @since 2023-09-12
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 用户登录：1.验证账号信息  2.将用户信息存入Redis 4.将用户令牌返回
     *
     * @param vo
     * @param request
     * @return
     */
    @Override
    public Map<String, Object> login(UserInfo vo, HttpServletRequest request) {
        //1.验证账号是否合法
        //1.1 根据登录账户/手机号/邮箱查询账号是否存在
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(vo.getPhone()) && StringUtils.isNotBlank(vo.getPassword())){
            //手机端
            queryWrapper.eq(UserInfo::getPhoneNum, vo.getPhone());
        }else{
            //PC端
            queryWrapper.eq(UserInfo::getLoginName, vo.getLoginName());
            queryWrapper.or().eq(UserInfo::getPhoneNum, vo.getLoginName());
            queryWrapper.or().eq(UserInfo::getEmail, vo.getLoginName());
        }
        UserInfo userInfoDB = this.getOne(queryWrapper);
        if (userInfoDB == null) {
            throw new RuntimeException("账号不存在！");
        }
        int status = userInfoDB.getStatus();
        if (0 == status) {
            throw new RuntimeException("账户被锁定！");
        }
        //1.2 判断密码是否一致
        //采用MD5对用户输入密码进行加密 跟数据库查询到记录中密码进行比较
        String userEnterPwd = "";
        if(StringUtils.isNotBlank(vo.getPhone()) && StringUtils.isNotBlank(vo.getPassword())){
            //手机端
            userEnterPwd = DigestUtils.md5DigestAsHex(vo.getPassword().getBytes());
        }else{
            //PC端
            userEnterPwd = DigestUtils.md5DigestAsHex(vo.getPasswd().getBytes());
        }
        if (!userInfoDB.getPasswd().equals(userEnterPwd)) {
            throw new RuntimeException("用户密码错误！");
        }

        //2.将用户信息存入Redis
        //2.1 构建用户登录key: 采用 user:login:UUID唯一令牌
        String token = UUID.randomUUID().toString();
        String loginKey = RedisConst.USER_LOGIN_KEY_PREFIX + token;
        //2.2 构建存入Redis中用户信息对象：包含用户ID，用户所在城市，用户手机设备标识
        JSONObject userRedisInfo = new JSONObject();
        userRedisInfo.put("id", userInfoDB.getId());
        //2.2.1 获取IP地址
        String ipAddress = IpUtil.getIpAddress(request);
        //2.2.2 通过IP地址获取所在城市
        try {
            AreaInfo areaInfo = BaiDuService.getArea(ipAddress);
            if (areaInfo != null) {
                String city = StringUtils.isNotBlank(areaInfo.getCity()) ? areaInfo.getCity() : areaInfo.getProvince();
                userRedisInfo.put("city", city); //所在城市
                userRedisInfo.put("eqid", "abc"); //用户移动端设备
            }
        } catch (Exception e) {
            log.error("[用户服务]获取用户城市异常：{}", e);
        }
        //2.3 将登录成功信息写入到Redis
        redisTemplate.opsForValue().set(loginKey, userRedisInfo, RedisConst.SKUKEY_TIMEOUT, TimeUnit.SECONDS);

        //3.按照接口要求响应业务数据
        Map<String, Object> mapResult = new HashMap<>();
        mapResult.put("token", token);
        mapResult.put("nickName", userInfoDB.getNickName());
        return mapResult;
    }

    /**
     * 用户 退出
     *
     * @param token
     */
    @Override
    public void logout(String token) {
        String loginKey = RedisConst.USER_LOGIN_KEY_PREFIX + token;
        redisTemplate.delete(loginKey);
    }
}
